IPFORWARDING

Section: User Commands (1)
Updated: SRI Information Sciences and Technology Center
Index Return to Main Contents
 

IPFORWARDING

ipforwarding - check for hosts doing IP forwarding  

ORIGIN

SRI Information Sciences and Technology Center  

SYNOPSIS

ipforwarding interface [ broadcast-addr ] < address-file  

DESCRIPTION

Probes each host listed on standard input to see if it is guilty of IP forwarding. Uses the ethernet interface specified by ``interface'' to send probe packets. If a ``broadcast-addr'' is supplied, it is used as the IP broadcast address in the probe packet, if omitted, the IP broadcast address is deduced from the interface address. Since this program is ignorant of subnets, the ``broadcast-addr'' should be supplied in a subnetted environment.

The format of each line in the ``address-file'' is as follows:

ethernet-addr internet-addr hostname
The ``ethernet-addr'' is a colon-separated six-octed Ethernet address, the ``internet-addr'' may be either a hostname or a dotted-decimal Internet address, and the optional ``hostname'' is ignored. This format is identical to that output by the etherhostprobe program, so (for example):
etherhostprobe 128.18.0.1 128.18.255.254 | ipforwarding le0
would find all hosts on SRINET and check them for IP forwarding.

Each line from standard input is sent to standard output, preceded with an ``OK'' if the host is not guilty of IP forwarding, or with a ``NOTOK'' otherwise.

The ipforwarding program checks for IP forwarding by manufacturing a special ethernet packet that has a unicast Ethernet address and a new-style broadcast IP address and sending it out via Sun's NIT facility. If the target host echos this packet, it is deemed guilty of IP forwarding. Note that if the target host happens to be down, it will be (possibly incorrectly) deemed not guilty of IP forwarding.  

RETURN VALUE

Returns 0 if all went well, -1 if problems occurred.  

BUGS

Runs only on Suns.

Does not check for bad ICMP replies that are also capable of causing broadcast storms.

Will exonerate any host that is down.  

HISTORY

25-Nov-87
Written by Paul E. McKenney, SRI Information Sciences and Technology Center. RogueMonsterelse
  echo "will not overwrite ./ipforwarding.1" fi if [ `wc -c ./ipforwarding.1 | awk '{printf $1}'` -ne 2223 ] then echo `wc -c ./ipforwarding.1 | awk '{print "Got " $1 ", Expected " 2223}'` fi if `test ! -s ./ipforwarding.c` then echo "writing ./ipforwarding.c" cat > ./ipforwarding.c << 'RogueMonster' /************************************************************************
 *                                                                      *

 *      File:  ipforwarding.c                                           *

 *                                                                      *

 *      IPFORWARDING check routine.  Takes a list of ethernet and       *

 *      internet addresses of hosts on standard input, probes each host *

 *      to see if it has the ipforwarding bug.  Prints out its input    *

 *      lines, with each prefaced by either "OK   " or "NOTOK", as      *

 *      appropriate.                                                    *

 *                                                                      *

 *      Usage:                                                          *

 *              ipforwarding < addresslist                              *

 *      where `addresslist' might be the output of etherhostprobe.      *

 *                                                                      *

 *      Written 25-Nov-87 by Paul E. McKenney, SRI International.       *

 *      Copyright (c) 1987 SRI International.                           *

 *                                                                      *

 ************************************************************************/

/*
 *      $Log:   ipforwarding.c,v $

 * Revision 1.1  87/12/08  10:16:58  mckenney
 * Initial revision
 * 
 */

/* Include files.                                                       */

#include <stdio.h> #include <sys/types.h> #include <sys/signal.h> #include <sys/socket.h> #include <sys/time.h> #include <net/if.h> #include <netinet/in_systm.h> #include <netinet/in.h> #include <netinet/if_ether.h> #include <netinet/ip.h> #include <net/nit.h> #include <netdb.h> #include <setjmp.h>

/* Type definitions local to this file.                                 */

#define MAXTRIES        5               /* MAX. # transmit TRIES.       */
#define WAITTIME        1000000L        /* WAIT TIME between tries.     */

struct ether_ip         {
        struct ether_header eh;
        struct ip       ip;
        };

struct ether_iparp         {
        struct ether_header eh;
        struct ether_arp arp;
        };

/* Functions exported from this file.                                   */

/* Functions local to this file.                                        */

static void             catchalrm();    /* CATCH sigALRM's.             */
static int              catchpkt();     /* CATCH ethernet PacKeTs.      */

/* Variables exported from this file.                                   */

/* Variables local to this file.                                        */

static int              badhost;        /* is this a BAD HOST?          */
jmp_buf                 env;            /* ENVironment.                 */
struct ether_ip         packet;         /* outbound PACKET.             */
main(argc, argv)

        int             argc;
        char            *argv[];

        {
        char            cea[30];        /* Character version of EA.     */
        char            cia[30];        /* Character version of Ip Addr.*/
        struct ether_addr ea;           /* Ethernet Address.            */
        char            *em;            /* Error Message pointer.       */
        char            hostname[BUFSIZ]; /* HOST NAME buffer.          */
        int             i;
        struct itimerval itv;           /* Interval Timer Value.        */
        char            line[BUFSIZ];   /* input LINE.                  */
        int             nitin;          /* NIT INput socket.            */
        int             nitout;         /* NIT OUTput socket.           */
        int             ntries;         /* Number of TRIES at output.   */
        int             retval;         /* RETurn VALue.                */
        struct sockaddr_in sa;          /* current Socket Address.      */

        /* Check parameters.                                            */

        if ((argc < 2) ||
         (argc > 3))
                {
                fprintf(stderr, "Usage: %s interface [IPaddr], argv[0]);
                exit (-1);
                }

        /* Set up NIT sockets for raw ethernet interface.               */

        switch (nitout = mk_nit_snd(argv[1], &em))
        {

        case -1:

                fprintf(stderr, "Can't open NIT output: ");
                perror(em);
                exit(-1);

        case -2:

                fprintf(stderr, "Can't open NIT output: ");
                fprintf(stderr, "%s, em);
                exit(-1);
        }
        switch (nitin = mk_nit_chaste_filt(argv[1],
                                         ETHERTYPE_ARP,
                                         sizeof(struct ether_header) +
                                         sizeof(struct ether_arp),
                                         WAITTIME,
                                         &em))
        {

        case -1:

                fprintf(stderr, "Can't open NIT input: ");
                perror(em);
                exit(-1);

        case -2:

                fprintf(stderr, "Can't open NIT input: ");
                fprintf(stderr, "%s, em);
                exit(-1);
        }

        /* Find out who we are.                                         */

        (void)gethostname(hostname, sizeof(hostname));
        switch (tx_hostname(hostname, &sa, &em))
        {

        case -1:

                fprintf(stderr, "Can't find my name: ");
                perror(em);
                exit(-1);

        case -2:

                fprintf(stderr, "Can't find my name: ");
                fprintf(stderr, "%s, em);
                exit(-1);
        }

        /* Initialize the ethernet message type on the outgoing packet. */

        packet.eh.ether_type = ETHERTYPE_IP;

        /* Initialize the IP portion of the packet.                     */

        packet.ip.ip_v = IPVERSION;
        packet.ip.ip_hl = sizeof(struct ip) / 4;
        packet.ip.ip_tos = 0;
        packet.ip.ip_len = sizeof(struct ip);
        packet.ip.ip_id = 123;
        packet.ip.ip_off = 0;
        packet.ip.ip_ttl = 255;
        packet.ip.ip_p = 61;
        packet.ip.ip_sum = 0;
        packet.ip.ip_src = sa.sin_addr;
        packet.ip.ip_dst = sa.sin_addr;
        if (argc > 2)
                packet.ip.ip_dst.S_un.S_addr = inet_addr(argv[2]);
        else if (IN_CLASSA(packet.ip.ip_dst.S_un.S_addr))
                {
                packet.ip.ip_dst.S_un.S_un_b.s_b2 = 255;
                packet.ip.ip_dst.S_un.S_un_b.s_b3 = 255;
                packet.ip.ip_dst.S_un.S_un_b.s_b4 = 255;
                }
        else if (IN_CLASSB(packet.ip.ip_dst.S_un.S_addr))
                {
                packet.ip.ip_dst.S_un.S_un_b.s_b3 = 255;
                packet.ip.ip_dst.S_un.S_un_b.s_b4 = 255;
                }
        else if (IN_CLASSC(packet.ip.ip_dst.S_un.S_addr))
                packet.ip.ip_dst.S_un.S_un_b.s_b4 = 255;

        /* Set up to catch alarm signals.                               */

        signal(SIGALRM, catchalrm);

        /* Each pass through the following loop probes one host for     */
        /* the ipforwarding bug.                                        */

        while (fgets(line, sizeof(line), stdin) != NULL)
                {
                struct sockaddr_in dsa; /* Destination Socket Address.  */

                /* Break out the ethernet and IP addresses.             */
                /* Question (but otherwise ignore) bad lines.           */

                if (sscanf(line, "%25s %25s", cea, cia) != 2)
                        {
                        printf("%-6s %s", "???", line);
                        continue;
                        }
                if (!atoether(cea, &packet.eh.ether_dhost))
                        {
                        printf("%-6s %s", "?ea", line);
                        continue;
                        }
                if (tx_hostname(cia, &dsa, &em) < 0)
                        {
                        printf("%-6s %s", "?ia", line);
                        continue;
                        }

                /* Set up context for timeout.                          */

                ntries = 0;
                if (!setjmp(env) ||
                 (++ntries < MAXTRIES))
                        {

                        /* Transmit packet.                             */

                        if (nit_write(nitout, &packet, sizeof(packet)) < 0)
                                {
                                perror("nit_write failed");
                                exit(-1);
                                }

                        /* Set timer to wake us up after a second.      */

                        timerclear(&itv.it_interval);
                        itv.it_value.tv_sec = 1L;
                        itv.it_value.tv_usec = 0L;
                        (void)setitimer(ITIMER_REAL,
                                        &itv,
                                        (struct itimerval *)NULL);

                        /* Read ethernet packets . . .                  */

                        badhost = 0;
                        if (nit_read(nitin, catchpkt, &em) < 0)
                                {
                                perror("nit_read failed");
                                exit(-1);
                                }
                        }
                
                /* Print out the input line with the appropriate        */
                /* preface string.                                      */

                (void)printf("%-5s %s", badhost ? "NOTOK" : "OK", line);
                fflush(stdout);
                }

        exit (0);
        }
/* CATCH sigALRM signal, abort back to top level.                       */

static void catchalrm()

        {
        longjmp(env);
        }
/* CATCH ethernet PacKeT.                                               */

static int catchpkt(nh, pk, len)

        struct nit_hdr  *nh;            /* Nit Header.                  */
        char            *pk;            /* PacKet.                      */
        int             len;            /* LENgth of pk.                */

        {
        struct ether_iparp *arp         /* ARP packet pointer.          */
                                = (struct ether_iparp *)pk;
        int             i;

        /* If we have nothing to look at, leave.                        */

        if (pk == NULL)
                return (1);

        /* Sanity check on len.                                         */

        if (len < sizeof(*arp))
                return (1);

        /* Ignore any packets that are not arp requests.                */

        if (arp->arp.arp_op != ARPOP_REQUEST)
                return (1);

        /* Ignore any packets that are not broadcasts.                  */

        for (i = 0; i < sizeof(arp->eh.ether_dhost); i++)
                if (arp->eh.ether_dhost.ether_addr_octet[i] != 0xff)
                        return (1);

        /* Ignore any packets that are not from the current host.       */

        if (bcmp(&arp->eh.ether_shost,
                 &packet.eh.ether_dhost,
                 sizeof(arp->eh.ether_shost)) != 0)
                return (1);

        /* Ignore any packets that are not arp-ing for the broadcast    */
        /* address.                                                     */

        if (bcmp(arp->arp.arp_xtpa,
                 &packet.ip.ip_dst,
                 sizeof(arp->arp.arp_xtpa)) != 0)
                return (1);

        /* He's bad, set the flag. Do not tell the caller that we have  */
        /* seen enough so that we don't have to worry about the timer.  */

        badhost = 1;
        return (0);
        }
RogueMonsterelse
  echo "will not overwrite ./ipforwarding.c" fi if [ `wc -c ./ipforwarding.c | awk '{printf $1}'` -ne 7467 ] then echo `wc -c ./ipforwarding.c | awk '{print "Got " $1 ", Expected " 7467}'` fi if `test ! -s ./nit.3` then echo "writing ./nit.3" cat > ./nit.3 << 'RogueMonster'

 

NAME

mk_nit_snd - Make NIT output socket
mk_nit_chaste - Make ``chaste'' NIT input socket
mk_nit_chaste_filt - Make ``chaste'' filtered NIT input socket
mk_nit_promisc - Make promiscuous NIT input socket
mk_nit_promisc_filt - Make promiscuous filtered NIT input socket
mk_nit_rcv - Make specified type of NIT input socket
nit_read - NIT socket read/decode routine
 

ORIGIN

SRI Information Science and Technology Center  

SYNOPSIS

#include <libhelp.h>

int mk_nit_snd(device, errmsg)
char *device;
char **errmsg;

int mk_nit_chaste(device, snaplen, tout, errmsg)
char *device;
int snaplen;
unsigned long tout;
char **errmsg;

int mk_nit_chaste_filt(device, pktype, snaplen, tout, errmsg)
char *device;
unsigned int pktype;
int snaplen;
unsigned long tout;
char **errmsg;

int mk_nit_promisc(device, snaplen, tout, errmsg)
char *device;
int snaplen;
unsigned long tout;
char **errmsg;

int mk_nit_promisc_filt(device, pktype, snaplen, tout, errmsg)
char *device;
unsigned int pktype;
int snaplen;
unsigned long tout;
char **errmsg;

int mk_nit_rcv(device, promiscuous, pktype, snaplen, tout, errmsg)
char *device;
int promiscuous;
unsigned int pktype;
int snaplen;
unsigned long tout;
char **errmsg;

int nit_read(fd, rtn, errmsg)
int fd;
int (*rtn)();
char **errmsg;

int nit_write(fd, buf, len)
int fd;
char *buf;
int len;
 

DESCRIPTION

The `mk_nit_snd' routine creates an NIT socket suitable for writing raw packets to the specified interface (e.g., "ie0" or "le0").

The routines `mk_nit_chaste', `mk_nit_chaste_filt', `mk_nit_promisc',  `mk_nit_nit_promisc_filt', and `mk_nit_rcv' all create NIT sockets suitable for reading raw packets from the specified interface. These routines allow various options:

device

The name of the device to be read from, e.g., "ie0" or "le0".
promiscuous

If true, the specified device will be set to promiscuous mode. The routines with names containing `promisc' set this implicitly, the routines with names containing `chaste' reset this implicitly.
pktype

The types of packets to be accepted. There is a special type named `NT_ALLTYPES' that accepts any packet type. The routines that do not allow the packet types to be specified implicitly accept all packet types.
snaplen

The number of bytes to be snapped up as the packet goes by. The larger this number, the more difficult it will be for your program to keep up with network traffic. Setting the snaplen to be longer than the longest allowable packet will force all of the packet to be remembered.
tout

This is the length of time (in microseconds) that the kernel should hold packets in hopes of filling its internal buffer. If it has not managed to fill its internal buffer in this amount of time, it will transfer the partial buffer to your program. If tout is zero, the kernel will always wait until its buffer is full before giving any packets to your program.

The `nit_read' routine breaks the kernel's buffer down into packets, which it feeds one at a time to the function passed in through `rtn'. The `rtn' function will be called for every NIT header block present in the buffer. An NIT header block is present for each packet, for each group of lost packets (when you program is too slow to catch them!), and for the unlikely case that the timeout specified by the `tout' parameter to the routine that created the NIT socket expired without any packets showing up.

The `rtn' function will be passed three parameters:

nh

This is a pointer to the current NIT header (struct nit_hdr *). See nit(4) for more details.
pk

This is a pointer to the packet (or NULL if there is no packet).
len

This is the length of the portion of the packet that was kept by the kernel (see the `snaplen' parameter above).

The `rtn' function should return a `1' if it wishes to continue to receive packets, or a `0' if it has seen enough.

The `nit_write' routine dumps the contents of the specified buffer to the interface in raw mode. Note that the kernel may modify the source ethernet address to better reflect reality, and that the packet may be padded to fit size limitations.  

DIAGNOSTICS

All these routines return `-1' upon error, and point `errmsg' to a string describing the operation that caused the error. The variable `errno' is left alone, so the `perror' routine may be used to print a human-readable version of the error.  

BUGS

You must be super-user to call these routines.
The buffering capacity in the kernel is limited. It is almost impossible to avoid packet loss under heavy traffic in promiscuous mode.  

HISTORY

17-Nov-87
Written by Paul E. McKenney, SRI Information Science and Technology Center RogueMonsterelse
  echo "will not overwrite ./nit.3" fi if [ `wc -c ./nit.3 | awk '{printf $1}'` -ne 4787 ] then echo `wc -c ./nit.3 | awk '{print "Got " $1 ", Expected " 4787}'` fi if `test ! -s ./nit.c` then echo "writing ./nit.c" cat > ./nit.c << 'RogueMonster' /************************************************************************
 *                                                                      *

 *      File:  nit.c                                                    *

 *                                                                      *

 *      routines for handling a Network Interface Tap.                  *

 *                                                                      *

 *      Written 17-Nov-87 by Paul E. McKenney, SRI International,       *

 *      based on code written by Sam Bikkina (also of SRI) and on code  *

 *      written by Sun Microsystems, Inc.                               *

 *      Copyright (c) 1987 SRI International.                           *

 *                                                                      *

 ************************************************************************/

/*
 *      $Log:   nit.c,v $

 * Revision 2.0  88/09/23  18:28:16  mckenney
 * .
 * 
 * Revision 1.2  87/11/18  09:57:07  mckenney
 * Add nit_write routine.
 * 
 * Revision 1.1  87/11/18  09:45:11  mckenney
 * Initial revision
 * 
 */

/* Include files.                                                       */

#include <stdio.h> #include <errno.h> #include <sys/types.h> #include <sys/time.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <net/nit.h> #include <net/if.h>

/* Type definitions local to this file.                                 */

#define BUFSPACE        (4 * 8192)      /* kernel nit BUFfer SPACE.     */

/* Functions exported from this file.                                   */

extern int              mk_nit_snd();   /* MaKe NIT socket for SeNDing. */
extern int              mk_nit_chaste(); /* MaKe NIT for CHASTE rcv.    */
extern int              mk_nit_chaste_filt(); /* same, w/ type FILTer.  */
extern int              mk_nit_promisc(); /* MaKe NIT for PROMISC. rcv. */
extern int              mk_nit_promisc_filt(); /* same, w/ type FILTer. */
extern int              mk_nit_rcv();   /* MaKe NIT for ReCeiVe.        */
extern int              nit_read();     /* NIT socket READ/decode.      */
extern int              nit_write();    /* NIT socket WRITE packet.     */

/* Functions local to this file.                                        */

/* Variables exported from this file.                                   */

/* Variables local to this file.                                        */

/* MaKe an NIT socket for SeNDing arbitrary packets on the device whose */
/* name is passed as a string through `device'. This is currently      */
/* only guaranteed to work on ethernet devices. Returns a file         */
/* descriptor if all goes well, or -1 if not (in this case errno will   */
/* set to the error number, and errmsg will be pointed to a string that */
/* describes the attempted operation).                                  */

extern int mk_nit_snd(device, errmsg)

        char            *device;        /* name of DEVICE to send on.   */
        char            **errmsg;       /* pointer to ERRor MeSsaGe.    */

        {
        int             fd;             /* File Descriptor.             */
        struct nit_ioc  nioc;           /* Nit IOCtl parameter block.   */
        struct sockaddr_nit snit;       /* Sockaddr for NIT socket.     */
        
        /* Make the socket.                                             */

        if ((fd = socket(AF_NIT, SOCK_RAW, NITPROTO_RAW)) == -1)
                {
                *errmsg = "socket";
                return (-1);
                }

        /* Bind it to the specified device.                             */

        snit.snit_family = AF_NIT;
        strncpy(snit.snit_ifname, device, NITIFSIZ);
        if (bind(fd, &snit, sizeof(snit)) != 0)
                {
                *errmsg = "bind";
                return (-1);
                }

        /* Set up the input parameters. In this case, we don't want to */
        /* do any input . . .                                           */

        bzero(&nioc, sizeof(nioc));
        nioc.nioc_typetomatch = NT_NOTYPES;
        if (ioctl(fd, SIOCSNIT, &nioc) != 0)
                {
                *errmsg = "ioctl";
                return (-1);
                }

        /* All is well, return the file descriptor.                     */

        return (fd);
        }
/* MaKe an NIT socket for receiving (CHASTEly) packets on the           */
/* device whose name is passed as a string through `device'.            */
/* Packets received will be truncated to length `snaplen'. If the      */
/* kernel buffer has not been filled within `tout' microseconds, the    */
/* partial buffer collected by that time will be drained. A good value */
/* for `tout' is around 1000000 (one second). This routine is          */
/* currently only guaranteed to work on ethernet devices. It returns   */
/* a file descriptor if all goes well, or -1 if not (in this case errno */
/* will set to the error number, and errmsg will be pointed to a string */
/* that describes the attempted operation).                             */

extern int mk_nit_chaste(device, snaplen, tout, errmsg)

        char            *device;        /* name of DEVICE to send on.   */
        int             snaplen;        /* packet SNAPshot LENgth.      */
        unsigned long   tout;           /* TimeOUT (microseconds).      */
        char            **errmsg;       /* pointer to ERRor MeSsaGe.    */

        {

        /* Just dump this off on mk_nit_rcv.                            */

        return (mk_nit_rcv(device,
                         0,           /* non-promiscuous.             */
                         NT_ALLTYPES,
                         snaplen,
                         tout,
                         errmsg));
        }
/* MaKe an NIT socket for receiving (CHASTEly) packets on the           */
/* device whose name is passed as a string through `device' that are    */
/* of packet type `pktype'. Packets received will be truncated to      */
/* length `snaplen'. If the kernel buffer has not been filled within   */
/* `tout' microseconds, the partial buffer collected by that time will  */
/* be drained. A good value for `tout' is around 1000000 (one second). */
/* This routine is currently only guaranteed to work on ethernet        */
/* devices. It returns a file descriptor if all goes well, or -1 if    */
/* not (in this case errno will set to the error number, and errmsg     */
/* will be pointed to a string that describes the attempted operation). */

extern int mk_nit_chaste_filt(device, pktype, snaplen, tout, errmsg)

        char            *device;        /* name of DEVICE to send on.   */
        unsigned int    pktype;         /* desired PacKet TYPEs.        */
        int             snaplen;        /* packet SNAPshot LENgth.      */
        unsigned long   tout;           /* TimeOUT (microseconds).      */
        char            **errmsg;       /* pointer to ERRor MeSsaGe.    */

        {

        /* Just dump this off on mk_nit_rcv.                            */

        return (mk_nit_rcv(device,
                         0,           /* non-promiscuous.             */
                         pktype,
                         snaplen,
                         tout,
                         errmsg));
        }
/* MaKe an NIT socket for receiving (PROMISCuously) packets on the      */
/* device whose name is passed as a string through `device'.            */
/* Packets received will be truncated to length `snaplen'. If the      */
/* kernel buffer has not been filled within `tout' microseconds, the    */
/* partial buffer collected by that time will be drained. A good value */
/* for `tout' is around 1000000 (one second). This routine is          */
/* currently only guaranteed to work on ethernet devices. It returns   */
/* a file descriptor if all goes well, or -1 if not (in this case errno */
/* will set to the error number, and errmsg will be pointed to a string */
/* that describes the attempted operation).                             */

extern int mk_nit_promisc(device, snaplen, tout, errmsg)

        char            *device;        /* name of DEVICE to send on.   */
        int             snaplen;        /* packet SNAPshot LENgth.      */
        unsigned long   tout;           /* TimeOUT (microseconds).      */
        char            **errmsg;       /* pointer to ERRor MeSsaGe.    */

        {

        /* Just dump this off on mk_nit_rcv.                            */

        return (mk_nit_rcv(device,
                         1,           /* promiscuous.                 */
                         NT_ALLTYPES,
                         snaplen,
                         tout,
                         errmsg));
        }
/* MaKe an NIT socket for receiving (PROMISCuously) packets on the      */
/* device whose name is passed as a string through `device' that are    */
/* of packet type `pktype'. Packets received will be truncated to      */
/* length `snaplen'. If the kernel buffer has not been filled within   */
/* `tout' microseconds, the partial buffer collected by that time will  */
/* be drained. A good value for `tout' is around 1000000 (one second). */
/* This routine is currently only guaranteed to work on ethernet        */
/* devices. It returns a file descriptor if all goes well, or -1 if    */
/* not (in this case errno will set to the error number, and errmsg     */
/* will be pointed to a string that describes the attempted operation). */

extern int mk_nit_promisc_filt(device, pktype, snaplen, tout, errmsg)

        char            *device;        /* name of DEVICE to send on.   */
        unsigned int    pktype;         /* desired PacKet TYPEs.        */
        int             snaplen;        /* packet SNAPshot LENgth.      */
        unsigned long   tout;           /* TimeOUT (microseconds).      */
        char            **errmsg;       /* pointer to ERRor MeSsaGe.    */

        {

        /* Just dump this off on mk_nit_rcv.                            */

        return (mk_nit_rcv(device,
                         1,           /* promiscuous.                 */
                         pktype,
                         snaplen,
                         tout,
                         errmsg));
        }
/* MaKe an NIT socket for receiving packets on the device whose name is */
/* passed as a string through `device' that are of packet type          */
/* `pktype'. If `promiscuous' is nonzero, then all packets will be     */
/* looked at, instead of just those packets that were sent to this      */
/* host. Packets received will be truncated to length `snaplen'. If   */
/* the kernel buffer has not been filled within `tout' microseconds,    */
/* the partial buffer collected by that time will be drained. A good   */
/* value for `tout' is around 1000000 (one second). This routine is     */
/* currently only guaranteed to work on ethernet devices. It returns a */
/* file descriptor if all goes well, or -1 if not (in this case errno   */
/* will set to the error number, and errmsg will be pointed to a string */
/* that describes the attempted operation).                             */

extern int mk_nit_rcv(device, promiscuous, pktype, snaplen, tout, errmsg)

        char            *device;        /* name of DEVICE to send on.   */
        int             promiscuous;    /* PROMISCUOUS input?           */
        unsigned int    pktype;         /* desired PacKet TYPEs.        */
        int             snaplen;        /* packet SNAPshot LENgth.      */
        unsigned long   tout;           /* TimeOUT (microseconds).      */
        char            **errmsg;       /* pointer to ERRor MeSsaGe.    */

        {
        int             fd;             /* File Descriptor.             */
        struct nit_ioc  nioc;           /* Nit IOCtl parameter block.   */
        struct sockaddr_nit snit;       /* Sockaddr for NIT socket.     */
        
        /* Make the socket.                                             */

        if ((fd = socket(AF_NIT, SOCK_RAW, NITPROTO_RAW)) == -1)
                {
                *errmsg = "socket";
                return (-1);
                }

        /* Bind it to the specified device.                             */

        snit.snit_family = AF_NIT;
        strncpy(snit.snit_ifname, device, NITIFSIZ);
        if (bind(fd, &snit, sizeof(snit)) != 0)
                {
                *errmsg = "bind";
                return (-1);
                }

        /* Set up the input parameters.                                 */

        bzero(&nioc, sizeof(nioc));
        nioc.nioc_bufspace = 32768;
        nioc.nioc_chunksize = snaplen;
        nioc.nioc_typetomatch = pktype;
        nioc.nioc_snaplen = snaplen;
        nioc.nioc_bufalign = sizeof (int);
        nioc.nioc_bufoffset = 0;
        nioc.nioc_flags = ((tout == 0L) ? 0 : NF_TIMEOUT) |
                         ((promiscuous == 0) ? 0 : NF_PROMISC);
        nioc.nioc_timeout.tv_sec = tout / 1000000;
        nioc.nioc_timeout.tv_usec = tout % 1000000;
        if (ioctl(fd, SIOCSNIT, &nioc) != 0)
                {
                *errmsg = "ioctl";
                return (-1);
                }

        /* Return the socket fd.                                        */

        return (fd);
        }
/* NIT READ packets. This routine reads nit buffers from the specified */
/* nit socket. It breaks these buffers into packets. Each packet      */
/* received will be passed to `rtn', which must be of the form:         */
/*      int rtn(nh, pk, len)                                            */
/*              struct nit_hdr *nh;     Nit Header (NULL if invalid)    */
/*              char *pk;               PacKet (NULL if invalid)        */
/*              int len;                LENgth of pk.                   */
/* Rtn should return `1' if it wishes to receive more packets, `0' if   */
/* it has seen enough. nit_read will return `1' if all went well and   */
/* rtn eventually returned a `0', or nit_read will return `-1' if a     */
/* system call failed (in this case errno will be set to the Unix error */
/* number and the pointer errmsg will be set to the name of the failing */
/* system call). In all other cases, nit_read will never return.       */

extern int nit_read(fd, rtn, errmsg)

        int             fd;             /* nit File Descriptor.         */
        int             (*rtn)();       /* RouTiNe to pass packets to.  */
        char            **errmsg;       /* ERRor MeSsaGe.               */

        {
        unsigned char   buf[BUFSPACE];  /* capture BUFfer.              */
        int             cc;             /* Character Count.             */

        /* Each pass through the following loop reads one nit buffer    */
        /* from the kernel.                                             */

        while ((cc = read(fd, buf, sizeof (buf))) > 0)
                {
                register unsigned char *bp;     /* Buffer Pointer.      */
                register unsigned char *bufstop; /* BUFfer STOP addr.   */
                int             datalen;        /* DATA LENgth.         */
                register struct nit_hdr *nh;    /* Nit Header.          */
                unsigned char   *pp;            /* Packet Pointer.      */

                /* Call the routine with null packet to give it a       */
                /* chance to give up.                                   */

                if ((*rtn)(NULL, NULL, 0) == 0)
                        return (0);

                /* Find the end of the nit buffer.                      */

                bufstop = buf + cc;

                /* Each pass through the following loop extracts one    */
                /* NIT header (possibly with packet data) from the nit  */
                /* buffer.                                              */

                for (bp = buf;
                 bp < bufstop;
                 bp += ((sizeof(struct nit_hdr) +
                         datalen +
                         sizeof(int) -
                         1) & ~(sizeof (int)-1)))
                        {

                        /* Get pointer to header.                       */

                        nh = (struct nit_hdr *)bp;

                        /* Set up pointer to data based on nit state.   */

                        switch (nh->nh_state)
                        {
                        case NIT_CATCH :

                                pp = (unsigned char *)(bp + sizeof(*nh));
                                datalen = nh->nh_datalen;
                                break;

                        case NIT_SEQNO :
                        case NIT_NOMBUF :
                        case NIT_NOCLUSTER :
                        case NIT_NOSPACE :

                                pp = NULL;
                                datalen = 0;
                                break;

                        default :

                                /* NIT framing error, abort loop.       */

                                nh = NULL;
                                pp = NULL;
                                datalen = 0;
                                bp = bufstop;
                                break;

                        }

                        /* Invoke caller's routine to handle the        */
                        /* packet.                                      */

                        if ((*rtn)(nh, pp, datalen) == 0)
                                return (0);

                        }
                }

        /* Got an error, let the caller know.                           */

        *errmsg = "read";
        return (-1);
        }
/* NIT WRITE packet in raw mode. Note that the source address may be   */
/* modified by the kernel to prevent obvious masquerade attempts.       */
/* Stolen from the NIT(4p) man page.                                    */

extern int nit_write(fd, buf, len)

        int             fd;             /* nit File Descriptor.         */
        char            *buf;           /* output BUFfer.               */
        int             len;            /* LENgth of data to output.    */

        {
        struct sockaddr sa;             /* Socket Address.              */
        int             offset;         /* address part OFFSET.         */
        int             retval;         /* sendto RETurn VALue.         */

        extern int      errno;          /* ERRor NOmber.                */

        /* Set up socket address to contain first part of buffer.       */

        offset = sizeof(sa.sa_data);
        if (len < offset)
                {
                errno = EINVAL;
                return (-1);
                }
        sa.sa_family = AF_UNSPEC;
        bcopy(buf, sa.sa_data, offset);
        retval = sendto(fd, buf + offset, len - offset, 0, &sa, sizeof(sa));
        if (retval == -1)
                return (retval);
        else
                return (retval + offset);
        }
RogueMonsterelse
  echo "will not overwrite ./nit.c" fi if [ `wc -c ./nit.c | awk '{printf $1}'` -ne 13567 ] then echo `wc -c ./nit.c | awk '{print "Got " $1 ", Expected " 13567}'` fi if `test ! -s ./tx_hostname.3` then echo "writing ./tx_hostname.3" cat > ./tx_hostname.3 << 'RogueMonster'

 

NAME

tx_hostname - Translate host name to internet address
 

ORIGIN

SRI Information Science and Technology Center  

SYNOPSIS

#include <sys/types.h>
#include <netinet/in.h>

int tx_hostname(host, sa, em)
char *host;
struct sockaddr_in *sa;
char **em;
 

DESCRIPTION

Translates the ascii hostname or internet address passed in `host' into a socket address, the result is placed into the sockaddr_in pointed to by `sa'.  

DIAGNOSTICS

Returns `-1' if a system error occurs, and points `errmsg' to a string describing the operation that caused the error. The variable `errno' is left alone, so the `perror' routine may be used to print a human-readable version of the error.

If `tx_hostname' itself detects an error, a `-2' will be returned, and `errmsg' will be pointed to a human-readable description of the problem. The `errno' variable will be meaningless in this case.  

HISTORY

25-Nov-87
Written by Paul E. McKenney, SRI Information Science and Technology Center RogueMonsterelse
  echo "will not overwrite ./tx_hostname.3" fi if [ `wc -c ./tx_hostname.3 | awk '{printf $1}'` -ne 1052 ] then echo `wc -c ./tx_hostname.3 | awk '{print "Got " $1 ", Expected " 1052}'` fi if `test ! -s ./tx_hostname.c` then echo "writing ./tx_hostname.c" cat > ./tx_hostname.c << 'RogueMonster' /************************************************************************
 *                                                                      *

 *      File:  tx_hostname.c                                            *

 *                                                                      *

 *      TranslateX HOSTNAME to internet address.                        *

 *                                                                      *

 *      Written by Paul E. McKenney, SRI International.                 *

 *                                                                      *

 ************************************************************************/

/*
 *      $Log:   tx_hostname.c,v $

 * Revision 2.0  88/09/23  18:28:31  mckenney
 * .
 * 
 */

/* Include files.                                                       */

#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <strings.h>

/* Type definitions local to this file.                                 */

/* Functions exported from this file.                                   */

extern int              tx_hostname();  /* TranslateX HOSTNAME.         */

/* Functions local to this file.                                        */

/* Variables exported from this file.                                   */

/* Variables local to this file.                                        */
/* TranslateX HOSTNAME to internet address (the 'X' is silent).         */
/* Returns -1 if there was a system call problem, points em to a string */
/* containing the system call name.                                     */
/* Returns -2 if there were other problems and points em to a           */
/* string containing a human-readable error message.                    */
/* Returns host address in sa.                                          */

extern int tx_hostname(host, sa, em)

        char            *host;          /* HOST name or id.             */
        struct sockaddr_in *sa;         /* Socket Address.              */
        char            **em;           /* Error Message pointer.       */

        {
        char            errmsg[BUFSIZ]; /* ERRor MeSsaGe buffer.        */
        struct hostent  *hp;            /* Host entry Pointer.          */
        char            *rerrmsg;       /* Regex ERRor MeSsaGe.         */

        char            *re_comp();     /* regex library routines. No   */
        int             re_exec();      /* include files!!!!!!          */

        /* Initialize socket address.                                   */

        bzero((char *)sa, sizeof(*sa));
        sa->sin_family = AF_INET;

        /* Get host name -- check for internet address.                 */

        if ((rerrmsg =
         re_comp("[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*"))
         !=
         (char *)0)
                {
                sprintf(errmsg, "re_comp error: %s, rerrmsg);
                *em = errmsg;
                return (-2);
                }
        if (re_exec(host) == 1)
                {
                u_long          inet_addr();    /* Kludge around C bug. */

                sa->sin_addr.s_addr = inet_addr(host);
                }
        else if ((hp = gethostbyname(host)) == NULL)
                {
                sprintf(errmsg, "               *em = errmsg;
                return (-2);
                }
        else
                sa->sin_addr.s_addr = (u_long)hp->h_addr;

        return (0);
        }
RogueMonsterelse
  echo "will not overwrite ./tx_hostname.c" fi if [ `wc -c ./tx_hostname.c | awk '{printf $1}'` -ne 2329 ] then echo `wc -c ./tx_hostname.c | awk '{print "Got " $1 ", Expected " 2329}'` fi echo "Finished archive 1 of 3" exit


 

Index

IPFORWARDING
ORIGIN
SYNOPSIS
DESCRIPTION
RETURN VALUE
BUGS
HISTORY
NAME
ORIGIN
SYNOPSIS
DESCRIPTION
DIAGNOSTICS
BUGS
HISTORY
NAME
ORIGIN
SYNOPSIS
DESCRIPTION
DIAGNOSTICS
HISTORY

This document was created by man2html, using the manual pages.
Time: 11:58:49 GMT, November 04, 2024